<?php

namespace App\Repository;

use App\Common\Libs\ArrayHelper;
use App\Consts\GlobalConst;
use App\Consts\GlobalNoteConst;
use App\Consts\GlobalPackageConst;
use App\Models\IndexArticle;
use App\Models\IndexCollectPackage;
use App\Models\IndexNote;
use App\Models\SysDefaultCollectPackage;
use App\Models\UserCollect;
use App\Models\UserCollectPackage;
use Illuminate\Database\Eloquent\Builder;

/**
 * @package App\Repository
 * @see PackageRepository
 */
class PackageRepository extends BaseRepository
{
    /**
     * 获取某用户的某主体收藏记录
     * @param $userId
     * @param $packageId
     * @return \Illuminate\Database\Eloquent\Builder|UserCollectPackage|object|null
     */
    public function getCollectPackageByUserIdAndTargetId($userId, $packageId)
    {
        return UserCollectPackage::getInstance($userId)
            ->where('user_id', $userId)
            ->where('collect_package_id', $packageId)
            ->first();
    }

    /**
     * 获取用户收藏夹列表
     * @param $searchParams
     * @return Builder
     */
    public function getUserCollectPackageList($searchParams)
    {
        $provider = UserCollectPackage::getInstance($searchParams['user_id'])
            ->where('user_id', $searchParams['user_id'])
            ->whereIn('is_public', (array)$searchParams['is_public'])
            ->where('is_deleted', GlobalConst::IS_NOT_DELETE);

        if (array_key_exists('seen', $searchParams)) {
            $provider->where('collect_package_id', '<>', $searchParams['seen']);
        }

        if (!empty($searchParams['last_id'])) {
            $id = UserCollectPackage::getInstance($searchParams['user_id'])
                ->select(['id'])
                ->where('collect_package_id', $searchParams['last_id'])
                ->value('id');
            $provider->where('id', '<', $id);
        }

        $provider->orderByDesc('updated_at');
        $provider->orderByDesc('id');

        $pageSize = $searchParams['page_size'] ?? GlobalConst::BASE_PAGE_COUNT;
        return $this->setPagination($provider, ['page_size' => $pageSize]);
    }

    public function getCollectPackageTargetList($searchParams)
    {
        $indexCollectPackage = IndexCollectPackage::getInstance()
            ->where('collect_package_id', $searchParams['package_id'])
            ->first();
        if (!$indexCollectPackage) {
            return false;
        }

        $searchParams['user_id'] = $indexCollectPackage->user_id;
        $collectTableName = UserCollect::getTableNameById($indexCollectPackage->user_id);

        $provider = UserCollect::getInstance($indexCollectPackage->user_id)
            ->where($collectTableName . '.user_id', $searchParams['user_id'])
            ->where($collectTableName . '.package_id', $searchParams['package_id'])
            ->where($collectTableName . '.is_deleted', GlobalConst::IS_NOT_DELETE);
        if (array_key_exists('last_id', $searchParams)) {
            $collect = repository()->CollectRepository->getCollectByUserIdAndCollectId($indexCollectPackage->user_id, $searchParams['last_id']);
            if ($collect) {
                $provider->where($collectTableName . '.updated_at', '<', $collect->updated_at);
            }
        }

        $isPublic = [GlobalNoteConst::IS_PUBLIC];
        $targetIsDeleted = [GlobalConst::IS_NOT_DELETE];

        if ($searchParams['current_user_id'] == $indexCollectPackage->user_id) {
            $isPublic = [GlobalNoteConst::IS_NOT_PUBLIC, GlobalNoteConst::IS_PUBLIC];
            $targetIsDeleted = [GlobalConst::IS_NOT_DELETE, GlobalConst::IS_DELETED];
        }

        if ($searchParams['tab_type'] == GlobalPackageConst::TAB_TYPE_ALL) {
            $provider->leftJoin(IndexNote::tableName(), static function ($join) use ($collectTableName) {
                $join->on($collectTableName . '.target_id', '=', IndexNote::tableName() . '.note_id');
            });
            $provider->whereIn(IndexNote::tableName() . '.is_public', $isPublic)
                ->whereIn(IndexNote::tableName() . '.is_deleted', $targetIsDeleted)
                ->whereIn(IndexNote::tableName() . '.type', [GlobalNoteConst::TYPE_ARTICLE_NOTE, GlobalNoteConst::TYPE_LINE_NOTE]);

            $provider->leftJoin(IndexArticle::tableName(), static function ($join) use ($collectTableName) {
                $join->on($collectTableName . '.target_id', '=', IndexArticle::tableName() . '.article_id');
            });
            $provider->orWhere(static function ($query) use ($searchParams, $collectTableName, $targetIsDeleted, $indexCollectPackage) {
                $query->where($collectTableName . '.user_id', $searchParams['user_id'])
                    ->where($collectTableName . '.package_id', $searchParams['package_id'])
                    ->where($collectTableName . '.is_deleted', GlobalConst::IS_NOT_DELETE)
                    ->whereIn(IndexArticle::tableName() . '.is_deleted', $targetIsDeleted);
                if (array_key_exists('last_id', $searchParams)) {
                    $collect = repository()->CollectRepository->getCollectByUserIdAndCollectId($indexCollectPackage->user_id, $searchParams['last_id']);
                    if ($collect) {
                        $query->where($collectTableName . '.updated_at', '<', $collect->updated_at);
                    }
                }
            });
        }

        if ($searchParams['tab_type'] == GlobalPackageConst::TAB_TYPE_ARTICLE) {
            $provider->leftJoin(IndexArticle::tableName(), static function ($join) use ($collectTableName) {
                $join->on($collectTableName . '.target_id', '=', IndexArticle::tableName() . '.article_id');
            });
            $provider->whereIn(IndexArticle::tableName() . '.is_deleted', $targetIsDeleted);
        }

        if ($searchParams['tab_type'] == GlobalPackageConst::TAB_TYPE_NOTE) {
            $provider->leftJoin(IndexNote::tableName(), static function ($join) use ($collectTableName) {
                $join->on($collectTableName . '.target_id', '=', IndexNote::tableName() . '.note_id');
            });
            $provider->whereIn(IndexNote::tableName() . '.is_public', $isPublic)
                ->whereIn(IndexNote::tableName() . '.is_deleted', $targetIsDeleted)
                ->whereIn(IndexNote::tableName() . '.type', [GlobalNoteConst::TYPE_ARTICLE_NOTE, GlobalNoteConst::TYPE_LINE_NOTE]);
        }

        if (array_key_exists('last_id', $searchParams)) {
            $collect = repository()->CollectRepository->getCollectByUserIdAndCollectId($indexCollectPackage->user_id, $searchParams['last_id']);
            if ($collect) {
                $provider->where($collectTableName . '.updated_at', '<', $collect->updated_at);
            }
        }

        $provider->select($collectTableName . '.*');

        $provider->orderBy($collectTableName . '.updated_at', GlobalConst::ORDER_TYPE_DESC);

        return $this->setPagination($provider);
    }

    /**
     * 新增收藏夹
     * @param $loadData
     * @return bool|UserCollectPackage
     */
    public function createCollectPackage($loadData)
    {
        $model = UserCollectPackage::getInstance($loadData['user_id'])
            ->where('user_id', $loadData['user_id'])
            ->where('name', $loadData['name'])
            ->first();
        if ($model) {
            return $model->updateFormat([
                'is_deleted' => GlobalConst::IS_NOT_DELETE,
                'description' => $loadData['description'] ?? '',
                'is_public' => $loadData['is_public'] ?? GlobalPackageConst::IS_NOT_PUBLIC,
                'updated_at' => time(),
            ]);
        }

        $collectPackage = UserCollectPackage::getModel($loadData['user_id'])->create($loadData);

        return $collectPackage ?: false;
    }

    public function createIndexCollectPackage($loadData)
    {
        $indexCollectPackage = IndexCollectPackage::getInstance()
            ->where('user_id', $loadData['user_id'])
            ->where('collect_package_id', $loadData['collect_package_id'])
            ->first();

        if ($indexCollectPackage) {
            $indexCollectPackage->update([
                'is_deleted' => GlobalConst::IS_NOT_DELETE,
            ]);
            return $indexCollectPackage;
        }

        $indexCollectPackage = IndexCollectPackage::getModel()->create($loadData);

        return $indexCollectPackage ?: false;
    }

    /**
     * 【已经查询到收藏夹】删除收藏夹
     * @param UserCollectPackage $collectPackage
     * @return UserCollectPackage|mixed
     */
    public function delCollectPackageBySelf($collectPackage)
    {
        IndexCollectPackage::getModel()
            ->where('collect_package_id', $collectPackage->collect_package_id)
            ->update(['is_deleted' => GlobalConst::IS_DELETED]);
        $collectPackage->total = 0;
        $collectPackage->save();
        return $collectPackage->update(['is_deleted' => GlobalConst::IS_DELETED]);
    }

    /**
     * 通过收藏夹ID删除收藏夹
     * @param $collectPackageId
     * @return false|UserCollectPackage
     */
    public function delCollectPackageById($collectPackageId)
    {
        $indexCollectPackage = IndexCollectPackage::getModel()
            ->where(['collect_package_id' => $collectPackageId])
            ->first();
        if (!$indexCollectPackage) {
            return false;
        }
        $collectPackage = $this->getCollectPackageById($collectPackageId);
        if (!$collectPackage) {
            return false;
        }
        $indexCollectPackage->update(['is_deleted' => GlobalConst::IS_DELETED]);
        $collectPackage->update(['is_deleted' => GlobalConst::IS_DELETED]);
        return $collectPackage;
    }

    /**
     * 修改收藏夹记录
     * @param UserCollectPackage $collectPackage
     * @param $loadData
     * @return int|bool
     */
    public function updateCollectPackage(UserCollectPackage $collectPackage, $loadData)
    {
        return $collectPackage->update($loadData);
    }

    /**
     * 修改收藏夹记录
     * @param UserCollectPackage $collectPackage
     * @param $loadData
     * @return int|bool
     */
    public function updateIndexCollectPackage(UserCollectPackage $collectPackage, $loadData)
    {
        return $collectPackage->index->update($loadData);
    }

    /**
     * 判断用户某名称的收藏夹是否存在
     * @param $userId
     * @param $packageId
     * @param $name
     * @return bool
     */
    public function judgeCollectPackageExistByName($userId, $packageId, $name)
    {
        $models = UserCollectPackage::getInstance($userId)
            ->select('collect_package_id')
            ->where('user_id', $userId)
            ->where('name', $name)
            ->get();

        return !in_array($packageId, ArrayHelper::getColumn($models, 'collect_package_id')) && count($models) >= 1;
    }

    /**
     * 获取一组系统默认收藏夹
     * @return SysDefaultCollectPackage[]|Builder[]|\Illuminate\Database\Eloquent\Collection
     */
    public function getDefaultCollectPackage()
    {
        return SysDefaultCollectPackage::getInstance()
            ->where('status', GlobalPackageConst::STATUS_NORMAL)
            ->where('is_deleted', GlobalConst::IS_NOT_DELETE)
            ->get();
    }

    /**
     * 通过名称获取收藏夹
     * @param $userId
     * @param $name
     * @return UserCollectPackage|mixed
     */
    public function getCollectPackageByName($userId, $name)
    {
        return UserCollectPackage::getInstance($userId)
            ->where('user_id', $userId)
            ->where('name', $name)
            ->first();
    }

    /**
     * 通过packageID获取收藏夹
     * @param $packageId
     * @return UserCollectPackage|bool|Builder|\Illuminate\Database\Eloquent\Model|object|null
     */
    public function getCollectPackageById($packageId)
    {
        $indexCollectPackage = IndexCollectPackage::getInstance()
            ->where('collect_package_id', $packageId)
            ->first();
        if (!$indexCollectPackage) {
            return false;
        }

        return UserCollectPackage::getInstance($indexCollectPackage->user_id)
            ->where('user_id', $indexCollectPackage->user_id)
            ->where('collect_package_id', $packageId)
            ->first();
    }

    /**
     * 通过userId和packageId获取收藏夹
     * @param $userId
     * @param $packageId
     * @return Builder|\Illuminate\Database\Eloquent\Model|object|null
     */
    public function getCollectPackageByUserIdAndId($userId, $packageId)
    {
        UserCollectPackage::getInstance($userId);
        return UserCollectPackage::getInstance($userId)
            ->where('user_id', $userId)
            ->where('collect_package_id', $packageId)
            ->first();
    }

    /**
     * 根据分表数找到一组收藏夹
     * @param $tableCount
     * @param $collectPackageId
     * @param array $selects
     * @return array|UserCollectPackage[]
     */
    public function getCollectPackageByTableCount($tableCount, $collectPackageId, $selects = ['*'])
    {
        return UserCollectPackage::getInstance($tableCount)
            ->select($selects)
            ->whereIn('collect_package_id', $collectPackageId)
            ->get();
    }
}
